(function(Wind) {
	var Version = "4.2.3";

	function $ir(element) {
		if (arguments.length > 1) {
			for (var i = 0, elements = [], length = arguments.length; i < length; i++) {
				elements.push($ir(arguments[i]));
			}
			return elements;
		}

		if (Object.prototype.toString.call(element) == "[object String]") {
			element = document.getElementById(element);
		}
		return element;
	}

	function extend(destination, source) {
		for (var property in source) {
			destination[property] = source[property];
		}
		return destination;
	}

	function include(destination, source) {
		for (var property in source) {
			destination.prototype[property] = source[property];
		}
		return destination;
	}

	var create = Object.create || function(obj) {
		function F() {}

		F.prototype = obj;
		return new F();
	};
	
	var jsModels = ["Sir0xb.js"];

	function require(path, callback) {
		if (jsModels.indexOf(path) != -1) {
			return true;
		} else {
			_get(path, function(data){
				jsModels.push(path);
				eval(data);
				callback.apply(this);
			});
		}
	}

	function _get(url, callback) {
		var ajax = false;
		if (window.XMLHttpRequest) {
			ajax = new XMLHttpRequest();
		} else if (window.ActiveXObject) {
			try {
				ajax = new ActiveXObject("Msxml2.XMLHTTP");
			} catch(e) {
				try {
					ajax = new ActiveXObject("Microsoft.XMLHTTP");
				} catch(e) {
					ajax = false;
				}
			}
		}
		if (!ajax) {
			throw ("加载文件失败!");
			return false;
		}

		ajax.open("get", url, true);
		ajax.send("");
		ajax.onreadystatechange = function() {
			if (ajax.readyState == 4) {
				if (ajax.status == 200) {
					callback(ajax.responseText);
				}
			}
		}
	}
	
	function proxy(fun){
		var self = this;
		return (function(){
			return fun.apply(this, arguments);
		});
	}
	
	extend(Wind, {
		$ir : $ir
	});

	extend($ir, {
		extend 	: 	extend,
		include : 	include,
		create 	: 	create,
		require	:	require,
		proxy   :	proxy,
		Version : 	Version
	});
})(window);

(function($ir){
	$ir.Util || ($ir.Util = {});
	
	var Browser = (function(){
        var ua = navigator.userAgent;
        var isOpera = Object.prototype.toString.call(window.opera) == "[object Opera]";
        return {
			IsNot:			!document,
            IE:             !!window.attachEvent && !isOpera,
            Opera:          isOpera,
            WebKit:         ua.indexOf("AppleWebKit/") > -1,
            Gecko:          ua.indexOf("Gecko") > -1 && ua.indexOf("KHTML") === -1,
            MobileSafari:   /Apple.*Mobile.*Safari/.test(ua)
        }
    })();
    
    function guid(format){
		format = format || "xxxx_xxxx";
		return format.toLowerCase().replace(/[xy]/g, function(c){
			var r = Math.random()*16|0, v = c == 'x' ? r : (r&0x3|0x8);
			return v.toString(16);
		}).toUpperCase();
	}

	var _toString = Object.prototype.toString;
	
	function isArray(object) {
        return _toString.call(object) == '[object Array]';
    }
    
    function isFunction(object) {
        return typeof object === 'function';
    }
    
    function isString(object) {
        return _toString.call(object) == '[object String]';
    }
    
    function isNumber(object) {
        return _toString.call(object) == '[object Number]';
    }
    
    function isUndefined(object) {
        return typeof object === 'undefined';
    }
    
    $ir.extend($ir.Util, {
    	Browser		:		Browser,
		guid		:   	guid,
		isArray		:       isArray,
        isFunction	:     	isFunction,
        isString	:       isString,
        isString	:       isNumber,
        isUndefined	:    	isUndefined
	});
})($ir);

(function($ir){
	$ir.Util || ($ir.Util = {});
	
	var Map = function(only){    	
        this._key = [];
        this._value = [];
        this._length = 0;
        this._only = only || false;
        
        function put(key, value){
            if(this._only && this._key.indexOf(key) != -1){
                return false;
            }else{
                this._key.push(key);
                this._value.push(value);
                this._length++;
                return true;
            }
        }
        
        function get(key){
            if(this._only && this._key.indexOf(key) != -1){
                return this._value[this._key.indexOf(key)];
            }else if(!this._only && this._key.indexOf(key) != -1){
                var _val = [];
                for(var i = 0; i < this._length; i++){
                    this._key[i] == key && _val.push(this._value[i]);
                }
                return _val;
            }else{
                return [];
            }
        }
        
        function remove(key, value){
            if($ir.Util.isUndefined(value)){
                var _index = this._key.indexOf(key);
                if(this._only && _index != -1){
                    this._key.splice(_index, 1);
                    this._value.splice(_index, 1);
					  this._length--;
                }else if(!this._only && _index != -1){
                    while(_index != -1){
                        this._key.splice(_index, 1);
                        this._value.splice(_index, 1);
                        _index = this._key.indexOf(key);
                        this._length--;
                    }
                }
            }else{
                for(var i = 0; i < this._length; i++){
                    if(this._key[i] == key && this._value[i] == value){
                        this._key.splice(i, 1);
                        this._value.splice(i, 1);
                        this._length--;
                    }
                }
            }
        }
        
        function length(){
            return this._length;
        }
        
        function isOnly(){
            return this._only;
        }
        
        function isDefined(key){
            return this._key.indexOf(key) == -1 ? false : true;
        }
        
        function toJSON(){
            var _json = '[';
            for(var i = 0; i < this._length; i++){
                _json += '"' + this._key[i] + '":"' + this._value[i] + '", ';
            }
            _json = _json.length != 1 ? _json.substring(0, _json.length - 2) : _json;
            _json += ']';
            return _json;
        }
        
        function toQueryString(){
            var _query = '';
            for(var i = 0; i < this._length; i++){
                _query += this._key[i] + '=' + this._value[i] + '&';
            }
            _query = _query.substring(0, _query.length - 1);
            return _query;
        }
        
        $ir.include(Map, {
            put:                put,
            get:                get,
            remove:             remove,
            length:             length,
            isOnly:             isOnly,
            isDefined:          isDefined,
            toJSON:             toJSON,
            toQueryString:      toQueryString
        });
    }
	
	$ir.extend($ir.Util, {
		Map:	Map
	});
})($ir);

(function($ir){	
	var Class = function(parent){
        var klass = function(){
            this.init.apply(this, arguments);
        }
        
        if(parent){
            function F(){};
            F.prototype = parent.prototype;
            klass.prototype = new F();
        }
        
        klass.fn = klass.prototype;
        
        klass.fn.init = function(){};
        
        klass.fn.parent = klass;
        klass._super = klass.__proto__;
        
        klass.extend = function(obj){
            var extended = obj.extended;
			$ir.extend(this, obj);
            if(extended) extended(klass);
        }
        
        klass.include = function(obj){
            var included = obj.included;
            $ir.include(this, obj);
            if(included) included(klass);
        }
        
        klass.proxy = $ir.proxy;
        klass.fn.proxy = klass.proxy;
        
        return klass;
    }
	
	$ir.extend($ir, {
		Class:		Class
	});
})($ir);

(function($ir){
	$ir.Event || ($ir.Event = {});
	
	function on(element, type, handler){
		element = $ir(element);
		
		if(element.addEventListener){
			element.addEventListener(type, handler, false);
		}else if(element.attachEvent){
			element.attachEvent("on" + type, handler);
		}else{
			element["on" + type] = handler;
		}
	}
	
	function un(element, type, handler){
		element = $ir(element);
		
		if(element.removeEventListener){
			element.removeEventListener(type, handler, false);
		}else if(element.detachEvent){
			element.detachEvent("on" + type, handler);
		}else{
			element["on" + type] = null;
		}
	}
	
	function fuse(ev, callback){
		this._callbacks || (this._callbacks = new $ir.Util.Map());
		this._callbacks.put(ev, callback);
        return this;
    }
	
	function unfuse(ev, callback){
        this._callbacks || (this._callbacks = new $ir.Util.Map());
        this._callbacks.remove(ev, callback);
    }
	
	function before(ev, callback){
        this._befores || (this._befores = new $ir.Util.Map());
        this._befores.put(ev, callback);
        return this;
    }
    
    function unbefore(ev, callback){
        this._befores || (this._befores = new $ir.Util.Map());
        this._befores.remove(ev, callback);
    }
    
    function after(ev, callback){
        this._afters || (this._afters = new $ir.Util.Map());
        this._afters.put(ev, callback);
        return this;
    }
    
    function unafter(ev, callback){
        this._afters || (this._afters = new $ir.Util.Map());
        this._afters.remove(ev, callback);
    }
	
	function fire(ev){
		var args = Array.prototype.slice.call(arguments, 0);
        
        var ev = args.shift();
        
        this._befores || (this._befores = new $ir.Util.Map());
        if(this._befores.isDefined(ev)){
            var _beffns = this._befores.get(ev);
            for(var i1 = 0, l1 = _beffns.length; i1 < l1; i1++){
                _beffns[i1].apply(this, args);
            }
        }
        
        this._callbacks || (this._callbacks = new $ir.Util.Map());
        if(this._callbacks.isDefined(ev)){
            var _callfns = this._callbacks.get(ev);
            for(var i2 = 0, l2 = _callfns.length; i2 < l2; i2++){
                _callfns[i2].apply(this, args);
            }
        }
        
        this._afters || (this._afters = new $ir.Util.Map());
        if(this._afters.isDefined(ev)){
            var _aftfns = this._afters.get(ev);
            for(var i3 = 0, l3 = _aftfns.length; i3 < l3; i3++){
                _aftfns[i3].apply(this, args);
            }
        }
        
        return this;
    }
	
	$ir.extend($ir.Event, {
		on:			on,
		un:			un,
		fuse:		fuse,
		unfuse:		unfuse,
		before:     before,
        unbefore:   unbefore,
        after:      after,
        unafter:    unafter,
		fire:		fire
	});
})($ir);

(function($ir){
	var Model = {
		inherited: function(){},
		created: function(){
			this.records = {};
			this.idFormat = "xxxx_xxxx_xxxx_xxxx";
		},
		
		prototype: {
			init: function(){}
		},
		
		create: function(){
			var object = $ir.create(this);
			object.parent = this;
			object.fn = object.prototype;
			object.fn = $ir.create(this.prototype);
			
			object.created();
			this.inherited(object);
			return object;
		},
		
		init: function(){
			var instance = $ir.create(this.prototype);
			instance.parent = this;
			instance.init.apply(instance, arguments);
			return instance;
		},
		
		extend: function(obj){
			var extended = obj.extended;
			$ir.extend(this, obj);
			if(extended) extended(this);
		},
		
		include: function(obj){
			var included = obj.included;
			$ir.include(this, obj);
			if(included) included(this);
		}
	}
	
	$ir.extend($ir, {
		Model:		Model
	});
})($ir);

(function($ir){
	var Model = $ir.Model;
	
	Model.include({
		newRecord: true,
		
		create: function(){
			this.id || (this.id = $ir.Util.guid(this.idFormat));
			this.newRecord = false;
			this.parent.records[this.id] = this.clone();
		},
		
		update: function(){
			this.parent.records[this.id] = this.clone();
		},
		
		save: function(){
			this.newRecord ? this.create() : this.update();
		},
		
		clone: function(){
			var F = {};
			$ir.extend(F, this);
			return F;
		},
		
		destroy: function(){
			delete this.parent.records[this.id];
		}
	});
	
	Model.extend({
		find: function(id){
			if(!this.records[id]){
				throw("Unknown record");
			}else{
				return this.records[id];
			}
		},
		
		load: function(data){
			this.records = {};
			
			for(var i in data){
				var record = this.init(data[i]);
				record.newRecord = false;
				record.id || (record.id = $ir.Util.guid(this.idFormat));
				this.records[record.id] = record;
			}
		}
	});
})($ir);

(function($ir){
	var Controller = {};
	
	function create(includes){
		var result = function(){
			this.init.apply(this, arguments);
		};
		
		result.fn = result.prototype;
		result.fn.init = function(){};
		
		result.proxy = $ir.proxy;
		result.fn = result.proxy;
		result.include = function(obj){
			$ir.include(this, obj);
		};
		result.extend = function(obj){
			$ir.extend(this, obj);
		};
		
		return result;
	}
	
	$ir.extend(Controller, {
		create :	create
	});
	
	$ir.extend($ir, {
		Controller :	Controller
	});
})($ir);
